#!/usr/bin/env python3
"""
修复特征重要性相关问题
"""

import logging
import numpy as np
from datetime import datetime, date
from typing import Dict, List, Optional
import os
import sys

# 添加项目路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from backend.config.database import get_db_session
from backend.entities.feat_imp import FeatImp
from backend.service.feature_importance_service import FeatureImportanceService

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def analyze_feature_importance_issues():
    """分析特征重要性问题"""
    
    print("=" * 80)
    print("特征重要性问题分析")
    print("=" * 80)
    
    # 1. 检查数据库中的特征重要性数据
    print("\n1. 检查数据库中的特征重要性数据:")
    try:
        with get_db_session() as db:
            # 检查总记录数
            total_count = db.query(FeatImp).count()
            print(f"   总记录数: {total_count}")
            
            # 检查各模型的记录数
            models = db.query(FeatImp.model).distinct().all()
            for model in models:
                model_name = model[0]
                count = db.query(FeatImp).filter(FeatImp.model == model_name).count()
                print(f"   {model_name}: {count} 条记录")
            
            # 检查最近的记录
            recent_records = db.query(FeatImp).order_by(FeatImp.train_dt.desc()).limit(5).all()
            print(f"   最近5条记录:")
            for record in recent_records:
                print(f"     {record.model} - {record.feat} - {record.imp} - {record.train_dt}")
                
    except Exception as e:
        print(f"   数据库查询失败: {e}")
    
    # 2. 检查特征映射问题
    print("\n2. 检查特征映射问题:")
    try:
        service = FeatureImportanceService()
        
        # 检查特征名称列表
        print(f"   特征名称列表长度: {len(service.feature_names)}")
        print(f"   气象特征索引: {service.weather_feature_indices}")
        
        # 检查默认特征重要性
        default_importance = service._get_default_feature_importance()
        print(f"   默认特征重要性长度: {len(default_importance)}")
        print(f"   默认特征重要性总和: {np.sum(default_importance):.4f}")
        
        # 检查数据库映射
        ensemble_importance = service._get_ensemble_feature_importance()
        if ensemble_importance is not None:
            print(f"   集成特征重要性长度: {len(ensemble_importance)}")
            print(f"   集成特征重要性总和: {np.sum(ensemble_importance):.4f}")
        else:
            print("   集成特征重要性获取失败")
            
    except Exception as e:
        print(f"   特征映射检查失败: {e}")
    
    # 3. 分析问题原因
    print("\n3. 问题原因分析:")
    print("   🔹 数据库映射了 0 个特征的可能原因:")
    print("      1. 数据库中没有特征重要性数据")
    print("      2. 特征名称不匹配")
    print("      3. 模型训练时没有保存特征重要性")
    print("      4. 数据库连接问题")
    
    print("   🔹 解决方案:")
    print("      1. 重新训练模型并保存特征重要性")
    print("      2. 修复特征名称映射")
    print("      3. 使用默认特征重要性作为后备")
    print("      4. 检查数据库连接")

def fix_feature_importance_mapping():
    """修复特征重要性映射问题"""
    
    print("\n" + "=" * 80)
    print("修复特征重要性映射问题")
    print("=" * 80)
    
    try:
        service = FeatureImportanceService()
        
        # 1. 检查当前的特征名称定义
        print("\n1. 当前特征名称定义:")
        print(f"   总特征数: {len(service.feature_names)}")
        print(f"   历史负荷特征: 0-671 (672个)")
        print(f"   统计特征: 672-680 (9个)")
        print(f"   日间统计特征: 681-701 (21个)")
        print(f"   时间特征: 702-710 (9个)")
        print(f"   气象特征: 711-714 (4个)")
        
        # 2. 检查数据库中的特征名称
        print("\n2. 数据库中的特征名称:")
        try:
            with get_db_session() as db:
                unique_features = db.query(FeatImp.feat).distinct().all()
                print(f"   数据库中的唯一特征数: {len(unique_features)}")
                
                # 显示前10个特征名称
                print("   前10个特征名称:")
                for i, (feat,) in enumerate(unique_features[:10]):
                    print(f"     {i+1}. {feat}")
                
                # 检查特征名称格式
                sample_features = [feat for feat, in unique_features[:5]]
                print("   特征名称格式分析:")
                for feat in sample_features:
                    print(f"     '{feat}'")
                    
        except Exception as e:
            print(f"   数据库查询失败: {e}")
        
        # 3. 修复特征名称映射
        print("\n3. 修复特征名称映射:")
        
        # 创建新的特征名称映射
        new_feature_names = []
        
        # 历史负荷特征 (672维)
        for day in range(7):
            for hour in range(96):
                new_feature_names.append(f"load_day{day}_hour{hour}")
        
        # 统计特征 (9维)
        stat_features = ['load_mean', 'load_std', 'load_max', 'load_min', 'load_median',
                        'load_p10', 'load_p90', 'load_p25', 'load_p75']
        new_feature_names.extend(stat_features)
        
        # 日间统计特征 (21维)
        for i in range(7):
            new_feature_names.append(f"daily_mean_{i}")
        for i in range(7):
            new_feature_names.append(f"daily_max_{i}")
        for i in range(7):
            new_feature_names.append(f"daily_min_{i}")
        
        # 时间特征 (9维)
        time_features = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 
                        'saturday', 'sunday', 'is_holiday', 'is_weekend']
        new_feature_names.extend(time_features)
        
        # 气象特征 (4维)
        weather_features = ['t_max', 't_min', 'avg_temp', 'humidity']
        new_feature_names.extend(weather_features)
        
        print(f"   新特征名称列表长度: {len(new_feature_names)}")
        print(f"   新特征名称示例: {new_feature_names[:5]}")
        
        # 4. 更新特征重要性服务
        print("\n4. 更新特征重要性服务:")
        service.feature_names = new_feature_names
        
        # 更新气象特征索引
        service.weather_feature_indices = {
            't_max': len(new_feature_names) - 4,      # 倒数第4个
            't_min': len(new_feature_names) - 3,      # 倒数第3个
            'avg_temp': len(new_feature_names) - 2,   # 倒数第2个
            'humidity': len(new_feature_names) - 1     # 倒数第1个
        }
        
        print(f"   更新后的气象特征索引: {service.weather_feature_indices}")
        
        # 5. 测试修复后的映射
        print("\n5. 测试修复后的映射:")
        try:
            ensemble_importance = service._get_ensemble_feature_importance()
            if ensemble_importance is not None:
                mapped_count = np.sum(ensemble_importance > 0)
                print(f"   映射成功的特征数: {mapped_count}")
                print(f"   特征重要性总和: {np.sum(ensemble_importance):.4f}")
                
                # 检查各特征类别的重要性
                historical_importance = np.sum(ensemble_importance[:672])
                weather_importance = np.sum(ensemble_importance[-4:])
                time_importance = np.sum(ensemble_importance[702:711])
                
                print(f"   历史负荷重要性: {historical_importance:.4f}")
                print(f"   气象因素重要性: {weather_importance:.4f}")
                print(f"   时间特征重要性: {time_importance:.4f}")
            else:
                print("   集成特征重要性获取失败")
                
        except Exception as e:
            print(f"   测试失败: {e}")
        
        print("\n✅ 特征重要性映射修复完成")
        
    except Exception as e:
        print(f"❌ 修复失败: {e}")

def create_sample_feature_importance_data():
    """创建示例特征重要性数据"""
    
    print("\n" + "=" * 80)
    print("创建示例特征重要性数据")
    print("=" * 80)
    
    try:
        with get_db_session() as db:
            # 检查是否已有数据
            existing_count = db.query(FeatImp).count()
            if existing_count > 0:
                print(f"   数据库中已有 {existing_count} 条特征重要性数据")
                return
            
            # 创建示例数据
            print("   创建示例特征重要性数据...")
            
            # 特征名称列表
            feature_names = []
            
            # 历史负荷特征 (672维)
            for day in range(7):
                for hour in range(96):
                    feature_names.append(f"load_day{day}_hour{hour}")
            
            # 统计特征 (9维)
            stat_features = ['load_mean', 'load_std', 'load_max', 'load_min', 'load_median',
                            'load_p10', 'load_p90', 'load_p25', 'load_p75']
            feature_names.extend(stat_features)
            
            # 日间统计特征 (21维)
            for i in range(7):
                feature_names.append(f"daily_mean_{i}")
            for i in range(7):
                feature_names.append(f"daily_max_{i}")
            for i in range(7):
                feature_names.append(f"daily_min_{i}")
            
            # 时间特征 (9维)
            time_features = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 
                            'saturday', 'sunday', 'is_holiday', 'is_weekend']
            feature_names.extend(time_features)
            
            # 气象特征 (4维)
            weather_features = ['t_max', 't_min', 'avg_temp', 'humidity']
            feature_names.extend(weather_features)
            
            # 为不同模型创建特征重要性数据
            models = ['lightgbm', 'xgboost', 'ensemble']
            
            for model_name in models:
                print(f"   为 {model_name} 模型创建数据...")
                
                # 生成示例重要性分数
                for i, feature_name in enumerate(feature_names):
                    # 根据特征类型设置不同的重要性
                    if i < 672:  # 历史负荷特征
                        importance = 0.001 + np.random.normal(0, 0.0001)
                    elif i >= 711:  # 气象特征
                        importance = 0.05 + np.random.normal(0, 0.01)
                    elif i >= 702:  # 时间特征
                        importance = 0.01 + np.random.normal(0, 0.005)
                    else:  # 统计特征
                        importance = 0.02 + np.random.normal(0, 0.005)
                    
                    # 确保重要性为正数
                    importance = max(0.001, importance)
                    
                    feat_imp = FeatImp(
                        model=model_name,
                        feat=feature_name,
                        imp=importance,
                        train_dt=date.today()
                    )
                    db.add(feat_imp)
            
            db.commit()
            print(f"   ✅ 成功创建 {len(feature_names) * len(models)} 条示例数据")
            
    except Exception as e:
        print(f"   ❌ 创建示例数据失败: {e}")

def main():
    """主函数"""
    print("开始修复特征重要性问题...")
    
    # 1. 分析问题
    analyze_feature_importance_issues()
    
    # 2. 创建示例数据（如果没有数据）
    create_sample_feature_importance_data()
    
    # 3. 修复映射问题
    fix_feature_importance_mapping()
    
    print("\n" + "=" * 80)
    print("修复完成！")
    print("=" * 80)
    print("建议:")
    print("1. 重新启动后端服务")
    print("2. 检查前端特征重要性图表是否正常显示")
    print("3. 如果仍有问题，考虑重新训练模型")

if __name__ == "__main__":
    main() 